/**
 * Copyright (c) 2009 blurredVision
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 * associated documentation files (the "Software"), to deal in the Software without restriction, 
 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or 
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 
 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 
 * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#include "StdAfx.h"
#include "ILight.h"
#include "core/core.h"
#include "dx/Light.h"

bool operator < (const ILight& l1, const ILight &l2)
{ 
	return l1.dist < l2.dist; 
}

ILight::ILight(void)
 :	fExponent(0.0f),
	fCutoff(0.0f)
{
	slight.position = math::Vector4(0,0,0,0);
	slight.diffuseColor = math::Vector4(1,1,1,1);
	slight.ambientColor = math::Vector4(0.0f, 0.0f, 0.0f, 1.0f);
	slight.specularColor = math::Vector4(1,1,1,1);
	slight.attenuation = math::Vector3(-1, -1, -1);
}

ILight::~ILight(void)
{
}

ILight* ILight::createDirectionalLight(const math::Vector4 &direction, float range, const math::Vector3 &color)
{
	ILight* light = new ILight();

	light->slight.lightType = LIGHT_DIRECTIONAL;
	light->slight.position = direction;
	light->slight.diffuseColor = color;
	light->slight.ambientColor = color;
	light->slight.specularColor = color;
	light->slight.attenuation = math::Vector3(range, range, range);
	light->updateBoundingSphere();
	return light;
}

ILight* ILight::createPointLight(const math::Vector4 &position, float range, const math::Vector3 &color)
{
	return createPointLight(position, math::Vector3(range, range, range), color);
}

ILight* ILight::createPointLight(const math::Vector4 &position, const math::Vector3 &range, const math::Vector3 &color)
{
	ILight* light = new ILight();

	light->slight.lightType = LIGHT_POINT;
	light->slight.position = position;
	light->slight.diffuseColor = color;
	light->slight.ambientColor = color;
	light->slight.specularColor = color;
	light->updateBoundingSphere();
	return light;
}


LightType ILight::getLightType() const 
{ 
	return (LightType)slight.lightType; 
}

void ILight::setLightType(LightType type)
{
	slight.lightType = type;
}

const math::Vector4& ILight::getPosition() const 
{ 
	return slight.position; 
}

const math::Vector4& ILight::getDirection() const
{
	return slight.position;
}

const math::Vector3& ILight::getDiffuseColor() const 
{ 
	return slight.diffuseColor;
}

const math::Vector3& ILight::getAmbientColor() const 
{ 
	return slight.ambientColor;
}

const math::Vector3& ILight::getSpecularColor() const 
{ 
	return slight.specularColor; 
}

const math::Vector3& ILight::getRange() const 
{ 
	return slight.attenuation;
}

void ILight::setPosition(const math::Vector4 &position)
{
	slight.position = position;
	updateBoundingSphere();
}

void ILight::setDirection(const math::Vector4 &direction)
{
	slight.position = direction;
	updateBoundingSphere();
}

void ILight::setDiffuseColor(const math::Vector3 &color)
{
	slight.diffuseColor = color;
}

void ILight::setAmbientColor(const math::Vector3 &color)
{
	slight.ambientColor = color;
}

void ILight::setSpecularColor(const math::Vector3 &color)
{
	slight.specularColor = color;
}

void ILight::setRange(const math::Vector3 &range)
{
	slight.attenuation = range;
	updateBoundingSphere();
}

void ILight::updateBoundingSphere()
{
	m_bbSphere.setSize( math::Vector3(&slight.position.x), max(max(slight.attenuation.x, slight.attenuation.y), slight.attenuation.z) );
}

model::BoundingSphere* ILight::getBoundingSphere()
{
	return &m_bbSphere;
}

const sShaderLight& ILight::getShaderLight() const
{
	return slight;
}